﻿// 
//    Copyright 2010 The JaernCloud Project
// 
//    Licensed under the Apache License, Version 2.0 (the "License");
//    you may not use this file except in compliance with the License.
//    You may obtain a copy of the License at
// 
//        http://www.apache.org/licenses/LICENSE-2.0
// 
//    Unless required by applicable law or agreed to in writing, software
//    distributed under the License is distributed on an "AS IS" BASIS,
//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//    See the License for the specific language governing permissions and
//    limitations under the License.
// 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using JaernCloud.Language.Runtime;
using JaernCloud.Language.Compiler.Types;
using JaernCloud.Web.Controllers;
using JaernCloud.Language.Runtime.Scopes;

namespace JaernCloud.Web.Scopes {
    public class NodeObjectScopeProvider : INodeObjectScopeProvider {
        
        private PrototypeNodeObjectScope _prototype;
        private RequestNodeObjectScope _request;
        private SessionNodeObjectScope _session;
        private ApplicationNodeObjectScope _application;
        private ConversationObjectScope _conversaton;

        public NodeObjectScopeProvider(JaernCloudController controller) {
            this.Controller = controller;
            this._prototype = new PrototypeNodeObjectScope();
            this._request = new RequestNodeObjectScope(controller);
            this._session = new SessionNodeObjectScope(controller);
            this._application = new ApplicationNodeObjectScope(controller);
            this._conversaton = new ConversationObjectScope(controller);

        }

        public INodeObjectScope Prototype       { get { return GetNodeObjectScope(NodeTypeScope.Prototype); } }
        public INodeObjectScope Request         { get { return GetNodeObjectScope(NodeTypeScope.Request); } }
        public INodeObjectScope Conversation    { get { return GetNodeObjectScope(NodeTypeScope.Conversation); } }
        public INodeObjectScope Session         { get { return GetNodeObjectScope(NodeTypeScope.Session); } }
        public INodeObjectScope Application     { get { return GetNodeObjectScope(NodeTypeScope.Application); } }
        public INodeObjectScope Persisted       { get { return GetNodeObjectScope(NodeTypeScope.Persisted); } }

        public virtual INodeObject<IScopedNodeType> Get(IScopedNodeType nodeType, INodeObjectGenerator nodeObjectGenerator) {
            
            if (nodeType.Scope == NodeTypeScope.Persisted) {
                // TODO: FIX THIS TEMP HACK! (override persisted to conversation for now to make ajaxcounter work)
                var persistence = Controller.Configuration.GetPersistenceSettings(nodeType);
                return GetNodeObjectScope(persistence).Get(nodeType, nodeObjectGenerator);
            }

            var scope = GetNodeObjectScope(nodeType.Scope);
            return scope.Get(nodeType, nodeObjectGenerator);
        }

        public virtual INodeObject<IScopedNodeType> Put(IScopedNodeObject<IScopedNodeType> nodeObject) {
            
            if (nodeObject.Type.Scope == NodeTypeScope.Persisted) {
                // TODO: FIX THIS TEMP HACK! (override persisted to conversation for now to make ajaxcounter work)
                var persistence = Controller.Configuration.GetPersistenceSettings(nodeObject.Type);
                return GetNodeObjectScope(persistence).Put(nodeObject);
            }

            var scope = GetNodeObjectScope(nodeObject.Type.Scope);
            return scope.Put(nodeObject);
        }

        public virtual INodeObjectScope GetNodeObjectScope(NodeTypeScope typeScope) {
            switch (typeScope) {
                case NodeTypeScope.Prototype:
                    return _prototype;
                case NodeTypeScope.Request:
                    return _request;
                case NodeTypeScope.Conversation:
                    return _conversaton;
                case NodeTypeScope.Session:
                    return _session;
                case NodeTypeScope.Application:
                    return _application;
                case NodeTypeScope.Persisted:
                    // TODO
                    break;
            }
            throw new NotSupportedException(typeScope + " is not supported");
        }

        public JaernCloudController Controller { get; private set; }

    }
}
